-- 自动售货机

-- 状态
-- s0, 
-- s1, 投入币值为5角
-- s2, 投入币值位1元
-- s3，投入币值位1.5元
-- s4，投入币值位2元

-- coin_in
-- coin_in(0) = 1 投入5角
-- coin_in(1) = 1 投入1元

-- goods_out
-- goods_out(0) = 1 输出货物
-- goods_out(1) = 1 找5角零钱

-- led1 led2 显示投入币值 0, 0.5, 1, 2

-- led_out 8段数码管输出
-----------------------------------

entity vending is
    port(
        clk, reset : in std_logic;
        coin_in : in std_logic_vector(2 downto 0);
        goods_out : out std_logic_vector(2 downto 0);   
        led_cs : out std_logic_vector(1 downto 0);
        led_out : out std_logic_vector(7 downto 0);
    );
    generic(
        ZERO : std_logic_vector(7 downto 0) := ""; 
        ZERODOT : std_logic_vector(7 downto 0) := ""; 
        ONEDOT : std_logic_vector(7 downto 0) := ""; 
        FIVE : std_logic_vector(7 downto 0) := ""; 
        ONE : std_logic_vector(7 downto 0) := ""; 
        TWO : std_logic_vector(7 downto 0) := ""; 
    );
end vending;

architecture behave of vending is
    type state_type is (s0, s1, s2, s3, s4);
    signal state : state_type;
    signal led_out0 : std_logic_vector(7 downto 0);
    signal led_out1 : std_logic_vector(7 downto 0);
    signal cnt : std_logic;
begin

    change_state: process(clk, reset) begin 
        if reset then 
            state <= 0;
        elsif clk'event and clk = '1' then
            case state is
                when s0 => if coin_in(0) = '1' then
                                state <= s1;
                           elsif coin_in(1) = '1' then
                                state <= s2;
                            end if;
                when s1 => if coin_in(0) = '1' then
                                state <= s2;
                            elsif coin_in(1) = '1' then
                                state <= s3;
                            end if;
                when s2 => if coin_in(0) = '1' then
                                state <= s3;
                            elsif coin_in(1) = '1' then
                                state <= s4;
                            end if;
                when s3 =>  if coin_in(0) = '1' then  -- 和s0一样
                                state <= s1;
                            elsif coin_in(1) = '1' then
                                state <= s2;
                            end if;
                when s4 =>  if coin_in(0) = '1' then  -- 和s1一样
                                state <= s2;
                            elsif coin_in(1) = '1' then
                                state <= s3;
                            end if;
                end case;

        end if;
    end process;

    process(state, coin_in) begin
   
        case state is
            when s0 => led_out1 <= ZERO; led_out0 <= ZERO;
                        goods_out = "00";
            when s1 => led_out1 <= ZERODOT; led_out0 <= FIVE;
                        goods_out = "00";
            when s2 => led_out1 <= ZERO; led_out0 <= "1";
                        goods_out = "00";
            when s3 => led_out1 <= ONEDOT; led_out0 <= FIVE;
                        goods_out = "10";
            when s4 => led_out1 <= ZERO; led_out0 <= TWO;
                        goods_out = "11";
        end case;

    end process;

    -- 分频（cnt）
    process(clk) begin
        if reset = '1' then cnt <= '0';
        elsif clk'event and clk = '1' then cnt <= not cnt;
        end if;
    end process;

    -- 数码管扫描电路
    process(cnt) begin
        if cnt = '0' then led_cs <= "00"; led_out <= led_out0;
        elsif cnt = '1' then led_cs <= "01"; led_out <= led_out1;
        else led_cs <= "00";
        end if;
    end process;

end behave;